Angular 简介和特性
1. 什么是 Angular?
Angular 是一个由 Google 开发和维护的开源前端框架,用于构建动态的单页应用(SPA)。它基于 TypeScript,提供了强大的工具和库来简化前端开发过程。Angular 的核心特性包括组件化、依赖注入、模块化、双向数据绑定等。
1.1 Angular 的历史
Angular 最初由 Google 在 2010 年发布,名为 AngularJS。随着前端技术的快速发展,AngularJS 在 2016 年升级为 Angular 2,并采用了全新的架构和语言(TypeScript)。此后,Angular 经历了多个版本的迭代,目前最新版本为 Angular 14。
1.2 Angular 的主要特性
- 组件化:Angular 应用由多个组件组成,每个组件负责特定的功能模块。
- 双向数据绑定:数据模型和视图之间的自动同步。
- 依赖注入:简化组件和服务之间的依赖管理。
- 模块化:通过模块组织代码,提高代码的可维护性和可重用性。
- 强大的 CLI 工具:提供命令行工具,简化开发流程。
2. 安装和环境搭建
在开始使用 Angular 之前,我们需要安装一些必要的工具和环境。
2.1 安装 Node.js 和 npm
Angular 依赖于 Node.js 和 npm(Node Package Manager)。首先,你需要安装 Node.js。安装完成后,npm 会自动安装。
# 检查 Node.js 和 npm 是否安装成功
node -v
npm -v
2.2 安装 Angular CLI
Angular CLI 是一个命令行工具,用于创建、构建和管理 Angular 项目。
# 全局安装 Angular CLI
npm install -g @angular/cli
# 检查 Angular CLI 是否安装成功
ng version
3. 创建第一个 Angular 应用
使用 Angular CLI 可以快速创建一个新的 Angular 项目。
# 创建一个新的 Angular 项目
ng new my-first-app
# 进入项目目录
cd my-first-app
# 启动开发服务器
ng serve
打开浏览器,访问 http://localhost:4200,你将看到一个简单的 Angular 应用。
4. Angular 项目结构
一个典型的 Angular 项目结构如下:
my-first-app/
├── src/
│ ├── app/
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ └── app.module.ts
│ ├── assets/
│ ├── environments/
│ ├── index.html
│ ├── main.ts
│ └── styles.css
├── angular.json
├── package.json
└── tsconfig.json
src/:包含应用的所有源代码。app/:包含应用的主要组件和模块。assets/:存放静态资源文件。environments/:包含不同环境的配置文件。index.html:应用的主 HTML 文件。main.ts:应用的入口文件。styles.css:全局样式文件。
5. 组件创建和使用
组件是 Angular 应用的基本构建块。每个组件由一个 TypeScript 类、一个 HTML 模板和一个 CSS 文件组成。
5.1 创建新组件
使用 Angular CLI 可以快速创建新组件。
# 创建一个名为 'hello-world' 的新组件
ng generate component hello-world
5.2 组件的结构
// hello-world.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-hello-world',
templateUrl: './hello-world.component.html',
styleUrls: ['./hello-world.component.css']
})
export class HelloWorldComponent {
title = 'Hello, World!';
}
<!-- hello-world.component.html -->
<h1>{{ title }}</h1>
/* hello-world.component.css */
h1 {
color: blue;
}
5.3 使用组件
在 app.component.html 中使用新创建的组件:
<!-- app.component.html -->
<app-hello-world></app-hello-world>
6. 模板语法
Angular 的模板语法允许你在 HTML 中嵌入动态内容。
6.1 插值表达式
使用双大括号 {{ }} 进行数据绑定。
<p>{{ title }}</p>
6.2 属性绑定
使用方括号 [] 进行属性绑定。
<img [src]="imageUrl">
6.3 事件绑定
使用圆括号 () 进行事件绑定。
<button (click)="onClick()">Click me</button>
7. 数据绑定
数据绑定是 Angular 的核心特性之一,它允许数据在组件和视图之间自动同步。
7.1 单向数据绑定
从组件到视图的数据绑定。
<p>{{ message }}</p>
7.2 双向数据绑定
使用 [(ngModel)] 实现双向数据绑定。
<input [(ngModel)]="name">
<p>Hello, {{ name }}!</p>
8. 生命周期钩子
Angular 组件具有生命周期钩子,允许你在组件的不同阶段执行代码。
8.1 常用生命周期钩子
ngOnInit:组件初始化时调用。ngOnChanges:输入属性变化时调用。ngOnDestroy:组件销毁时调用。
import { Component, OnInit, OnDestroy } from '@angular/core';
@Component({
selector: 'app-lifecycle',
template: `<p>{{ message }}</p>`
})
export class LifecycleComponent implements OnInit, OnDestroy {
message = 'Component is initializing...';
ngOnInit() {
this.message = 'Component is initialized!';
}
ngOnDestroy() {
console.log('Component is destroyed!');
}
}
9. 组件通信
组件之间可以通过 @Input 和 @Output 进行通信。
9.1 输入属性 (@Input)
父组件向子组件传递数据。
// parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `<app-child [message]="parentMessage"></app-child>`
})
export class ParentComponent {
parentMessage = 'Hello from Parent!';
}
// child.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>{{ message }}</p>`
})
export class ChildComponent {
@Input() message: string;
}
9.2 输出属性 (@Output)
子组件向父组件发送事件。
// child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `<button (click)="sendMessage()">Send Message</button>`
})
export class ChildComponent {
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit('Hello from Child!');
}
}
// parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `<app-child (messageEvent)="receiveMessage($event)"></app-child>`
})
export class ParentComponent {
receiveMessage(message: string) {
console.log(message);
}
}
10. 内置指令
Angular 提供了一些内置指令,用于操作 DOM 元素。
10.1 ngIf
根据条件显示或隐藏元素。
<p *ngIf="isVisible">This is visible!</p>
10.2 ngFor
循环渲染列表。
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
10.3 ngSwitch
根据条件选择不同的模板。
<div [ngSwitch]="condition">
<p *ngSwitchCase="'A'">Condition A</p>
<p *ngSwitchCase="'B'">Condition B</p>
<p *ngSwitchDefault>Default Condition</p>
</div>
11. 属性指令
属性指令用于修改 DOM 元素的外观或行为。
11.1 创建自定义属性指令
# 创建一个名为 'highlight' 的属性指令
ng generate directive highlight
// highlight.directive.ts
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight('yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
<!-- 使用自定义属性指令 -->
<p appHighlight>Hover over me!</p>
12. 结构指令
结构指令用于修改 DOM 结构,如添加或移除元素。
12.1 创建自定义结构指令
# 创建一个名为 'unless' 的结构指令
ng generate directive unless
// unless.directive.ts
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appUnless]'
})
export class UnlessDirective {
private hasView = false;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) {}
@Input() set appUnless(condition: boolean) {
if (!condition && !this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (condition && this.hasView) {
this.viewContainer.clear();
this.hasView = false;
}
}
}
<!-- 使用自定义结构指令 -->
<p *appUnless="condition">This is shown when condition is false.</p>
13. 自定义指令
自定义指令可以根据需求创建,用于扩展 Angular 的功能。
13.1 创建自定义指令
# 创建一个名为 'my-directive' 的自定义指令
ng generate directive my-directive
// my-directive.directive.ts
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appMyDirective]'
})
export class MyDirectiveDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {
renderer.setStyle(el.nativeElement, 'color', 'red');
}
}
<!-- 使用自定义指令 -->
<p appMyDirective>This text is red!</p>
14. 服务创建和使用
服务是 Angular 中用于处理业务逻辑的类。它们通常用于数据获取、状态管理等。
14.1 创建服务
# 创建一个名为 'data' 的服务
ng generate service data
// data.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
getData(): string {
return 'Hello from DataService!';
}
}
14.2 使用服务
// app.component.ts
import { Component } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-root',
template: `<p>{{ message }}</p>`
})
export class AppComponent {
message: string;
constructor(private dataService: DataService) {
this.message = this.dataService.getData();
}
}
15. 依赖注入原理
依赖注入(DI)是 Angular 的核心特性之一,用于管理组件和服务之间的依赖关系。
15.1 提供者配置
在 Angular 中,服务可以通过 @Injectable 装饰器进行配置。
// data.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
// ...
}
15.2 服务的作用域
服务的作用域可以通过 providedIn 属性进行配置。
'root':全局作用域,整个应用共享一个实例。'any':每个模块共享一个实例。'platform':平台级别的作用域。
16. 路由配置
Angular 提供了强大的路由功能,用于管理应用的导航。
16.1 配置路由
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
16.2 使用路由
<!-- app.component.html -->
<nav>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
</nav>
<router-outlet></router-outlet>
17. 路由参数
路由参数允许你在导航时传递数据。
17.1 配置带参数的路由
// app-routing.module.ts
const routes: Routes = [
{ path: 'user/:id', component: UserComponent }
];
17.2 获取路由参数
// user.component.ts
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-user',
template: `<p>User ID: {{ userId }}</p>`
})
export class UserComponent {
userId: string;
constructor(private route: ActivatedRoute) {
this.userId = this.route.snapshot.paramMap.get('id');
}
}
18. 子路由
子路由允许你在组件内部嵌套路由。
18.1 配置子路由
// app-routing.module.ts
const routes: Routes = [
{ path: 'user/:id', component: UserComponent, children: [
{ path: 'profile', component: UserProfileComponent },
{ path: 'settings', component: UserSettingsComponent }
]}
];
18.2 使用子路由
<!-- user.component.html -->
<nav>
<a routerLink="profile">Profile</a>
<a routerLink="settings">Settings</a>
</nav>
<router-outlet></router-outlet>
19. 路由守卫
路由守卫用于控制路由的访问权限。
19.1 创建守卫
# 创建一个名为 'auth' 的守卫
ng generate guard auth
// auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})